<?php
/**
 * @package es2reveng
 * @name ES2 .DBM bitmap to PNG converter
 * @author marco 'harddisk' schuster
 * @license GPL v3
 */

require 'helpers.php';
$f = $argv[1];
echo "viewing file $f\n";
if (!is_file($f))
	die("file broken");

$fp = fopen($f, "rb");

//check magic bytes
$offset = -1; //the ++ incrementor will read at byte 1 if this is omitted
$magic = getchar($fp, ++$offset);
$magic .= getchar($fp, ++$offset);
$magic .= getchar($fp, ++$offset);
$magic .= getchar($fp, ++$offset);
if ($magic != "\x0e\x00\x28\x00")
	die("wrong magic code. this is not a valid DBM file!\n");

//get the file size (after the 8 bytes header)
$b1 = getchar($fp, ++$offset, false);
$b2 = getchar($fp, ++$offset, false);
$b3 = getchar($fp, ++$offset, false);
$b4 = getchar($fp, ++$offset, false);
$filesize = le_to_int($b1, $b2, $b3, $b4);

//get row count
$b1 = getchar($fp, ++$offset, false);
$b2 = getchar($fp, ++$offset, false);
$tex_dim = le_to_int($b1, $b2);

//get the column count
$b1 = getchar($fp, ++$offset, false);
$b2 = getchar($fp, ++$offset, false);
$tex_linelen = le_to_int($b1, $b2);

//get the block length
$b1 = getchar($fp, ++$offset, false);
$b2 = getchar($fp, ++$offset, false);
$tex_blocklen = le_to_int($b1, $b2);

//jump over the separator NUL byte at the end of header
if (getchar($fp, ++$offset, false) != 0)
	echo "warning at offset $offset: jumping over something which is NOT a termination null byte!\n";

//get the texture payload (rawdata) length
$b1 = getchar($fp, ++$offset, false);
$b2 = getchar($fp, ++$offset, false);
$b3 = getchar($fp, ++$offset, false);
$b4 = getchar($fp, ++$offset, false);
$tex_datalen = le_to_int($b1, $b2, $b3, $b4);
if ($tex_datalen != $tex_dim * $tex_linelen)
	echo "warning: payload length ($tex_datalen) != dim*linelen (".($tex_dim * $tex_linelen).")\n";

if ($tex_linelen % $tex_blocklen != 0)
	echo "warning: line length ($tex_linelen) is not a integer multiple of block length ($tex_blocklen)\n";

//over-jump two padding bytes
$pad = getchar($fp, ++$offset);
$pad .= getchar($fp, ++$offset);
if ($pad != "\x00\x00")
	echo "warning: header padding bytes are not zero ('".strtohex($pad)."')\n";

echo "image data: $filesize bytes header+file, $tex_datalen file bytes, $tex_dim lines at $tex_linelen chars each (bs $tex_blocklen)\n";

$colors=array();
$image=imagecreate($tex_linelen, $tex_dim);
for ($i = 0; $i < 256; $i++) {
	$rgb=rgb($i);
	$colors[$i]=imagecolorallocate($image, $rgb["r"],$rgb["g"],$rgb["b"]);
}
for ($r = 0; $r < $tex_dim; $r++) {
	for ($c = 0; $c < $tex_linelen; $c++) {
		$ch = getchar($fp, ++$offset, false);
		imagesetpixel($image, $c, $r, $colors[$ch]);
	}
}

imagepng($image,$f.".png");

if ($offset + 1 != filesize($f)) //take care: offset is null-based, file-size is not
	echo "arrived at structural end (offset is $offset, flen is ".filesize($f)."), but there are still some bytes left\n";
else
	echo "file parse OK\n";
?>